﻿using System;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace DotNet.Common
{
	public enum FindReplaceType
	{
		Find,
		Replace
	}

	public partial class FormFindAndReplace : Form
	{
		TextBoxBase m_textBox;

		public FormFindAndReplace()
		{
			InitializeComponent();
		}

		public void LoadTextBox(TextBoxBase textBox, FindReplaceType type)
		{
			Debug.Assert(textBox != null);

			m_textBox = textBox;

			if (!base.Visible)
			{
				base.Visible = true;
			}

			switch (type)
			{
				case FindReplaceType.Find:
					tabControlFindAndReplace.SelectTab(0);
					if (textBox.SelectionLength > 0)
						comboBoxFindContent_FindTab.Text = textBox.SelectedText;
					break;
				case FindReplaceType.Replace:
					tabControlFindAndReplace.SelectTab(1);
					if (textBox.SelectionLength > 0)
						comboBoxFindContent_ReplaceTab.Text = textBox.SelectedText;
					break;
			}
		}

		private void FormFindAndReplace_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (e.CloseReason == CloseReason.UserClosing)
			{
				this.Visible = false;
				e.Cancel = true;
			}
		}

		private void FormFindAndReplace_KeyDown(object sender, KeyEventArgs e)
		{
			if(e.Alt)
			{
				switch (e.KeyCode)
				{
					case Keys.D:
						tabControlFindAndReplace.SelectTab(0);
						break;
					case Keys.P:
						tabControlFindAndReplace.SelectTab(1);
						break;
				}
			}
		}

		private void btnClose_Click(object sender, EventArgs e)
		{
			base.Close();
		}

		private void tabControlFindAndReplace_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (tabControlFindAndReplace.SelectedIndex == 0)
			{
				base.AcceptButton = btnFindNext_FindTab;
				comboBoxFindContent_FindTab.Focus();
				comboBoxFindContent_FindTab.SelectAll();
			}
			else
			{
				base.AcceptButton = btnFindNext_ReplaceTab;
				comboBoxFindContent_ReplaceTab.Focus();
				comboBoxFindContent_ReplaceTab.SelectAll();
			}
		}

		private void comboBoxFindContent_FindTab_TextChanged(object sender, EventArgs e)
		{
			btnFindNext_FindTab.Enabled = (comboBoxFindContent_FindTab.Text.Length != 0);
		}

		private void comboBoxFindContent_ReplaceTab_TextChanged(object sender, EventArgs e)
		{
			btnReplace.Enabled = btnReplaceAll.Enabled = btnFindNext_ReplaceTab.Enabled = (comboBoxFindContent_ReplaceTab.Text.Length != 0);
		}

		private void btnFindNext_FindTab_Click(object sender, EventArgs e)
		{
			FindInTextBox(comboBoxFindContent_FindTab.Text);
		}

		private void btnFindNext_ReplaceTab_Click(object sender, EventArgs e)
		{
			FindInTextBox(comboBoxFindContent_ReplaceTab.Text);
		}

		private void btnReplace_Click(object sender, EventArgs e)
		{
			ReplaceInTextBox(comboBoxFindContent_ReplaceTab.Text, comboBoxReplace.Text);
		}

		private void btnReplaceAll_Click(object sender, EventArgs e)
		{
			ReplaceAllInTextBox(comboBoxFindContent_ReplaceTab.Text, comboBoxReplace.Text);
		}

		private bool FindInTextBox(string findContent)
		{
			Debug.Assert(m_textBox != null && findContent != null);

			int index = m_textBox.Text.IndexOf(findContent, m_textBox.SelectionStart + m_textBox.SelectionLength, StringComparison.OrdinalIgnoreCase);
			if (index >= 0)
			{
				m_textBox.SelectionStart = index;
				m_textBox.SelectionLength = findContent.Length;
			}
			else
			{
				index = m_textBox.Text.IndexOf(findContent, 0, StringComparison.OrdinalIgnoreCase);
				if (index >= 0)
				{
					m_textBox.SelectionStart = index;
					m_textBox.SelectionLength = findContent.Length;
				}
				else
				{
					CommonApp.RunInformationMessageBox(this, "没有找到如下文本:\r\n" + findContent);
					if(tabControlFindAndReplace.SelectedIndex == 0)
					{
						comboBoxFindContent_FindTab.Focus();
					}
					else
					{
						comboBoxFindContent_ReplaceTab.Focus();
					}

					return false;
				}
			}

			AddFindList(findContent);
			m_textBox.Focus();
			return true;
		}

		private void ReplaceInTextBox(string findContent,string replaceContent)
		{
			Debug.Assert(m_textBox != null || !string.IsNullOrEmpty(findContent) || replaceContent != null);

			if (FindInTextBox(findContent))
			{
				m_textBox.SelectedText = replaceContent;
				m_textBox.SelectionStart -= replaceContent.Length;
				m_textBox.SelectionLength = replaceContent.Length;

				AddReplaceList(replaceContent);
			}
		}

		private void ReplaceAllInTextBox(string findContent, string replaceContent)
		{
			Debug.Assert(m_textBox != null || !string.IsNullOrEmpty(findContent) || replaceContent != null);

			int index;
			int lastIndex = -1;
			int start = 0;
			int count = 0;
			int findLength = findContent.Length;
			int replaceLength = replaceContent.Length;
			System.Text.StringBuilder boxStr = new System.Text.StringBuilder(m_textBox.Text);

			while((index = boxStr.ToString().IndexOf(findContent, start, StringComparison.OrdinalIgnoreCase)) >= 0)
			{
				boxStr.Remove(index, findLength);
				boxStr.Insert(index,replaceContent);

				start = index + replaceLength;
				lastIndex = index;
				count++;
			}

			if (count > 0)
			{
				m_textBox.Text = boxStr.ToString();
				m_textBox.SelectionStart = lastIndex;
				m_textBox.SelectionLength = replaceContent.Length;

				AddFindList(findContent);
				AddReplaceList(replaceContent);

				CommonApp.RunInformationMessageBox(this, string.Format("找到并替换了{0}个匹配的文本",count));
				m_textBox.Focus();
			}
			else
			{
				CommonApp.RunInformationMessageBox(this, "没有找到如下文本:\r\n" + findContent);
				comboBoxFindContent_ReplaceTab.Focus();
			}
		}

		private void AddFindList(string findContent)
		{
			if (!comboBoxFindContent_FindTab.Items.Contains(findContent))
			{
				comboBoxFindContent_FindTab.Items.Add(findContent);
				comboBoxFindContent_ReplaceTab.Items.Add(findContent);
			}
		}

		private void AddReplaceList(string replaceContent)
		{
			if (!comboBoxReplace.Items.Contains(replaceContent))
			{
				comboBoxReplace.Items.Add(replaceContent);
			}
		}
	}
}
